package com.bl.student.service.biz.user.impl;

import com.bl.student.common.ApiResponseCode;
import com.bl.student.common.CommonServiceException;
import com.bl.student.common.enums.ValidStatus;
import com.bl.student.common.enums.WorkType;
import com.bl.student.common.utils.ListUtils;
import com.bl.student.common.utils.UUIDUtils;
import com.bl.student.dao.model.*;
import com.bl.student.dao.redis.UserInfoDao;
import com.bl.student.dao.redis.model.UserInfo;
import com.bl.student.dao.repository.*;
import com.bl.student.service.biz.comment.CommentService;
import com.bl.student.service.biz.hx.HxAuthService;
import com.bl.student.service.biz.user.UserService;
import com.bl.student.service.biz.vip.VipService;
import com.bl.student.service.vo.DelBody;
import com.bl.student.service.vo.DelListBody;
import com.bl.student.service.vo.information.MyPageVo;
import com.bl.student.service.vo.teacher.TeacherListVo;
import com.bl.student.service.vo.user.*;
import com.bl.student.tp.hx.user.HxUserApi;
import com.bl.student.tp.hx.user.HxUserInfoRequest;
import com.bl.student.tp.hx.user.HxUserInfoResponse;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by yujingyi on 2018/1/15.
 */
@Service
@Log4j2
public class UserServiceImpl implements UserService {

    final static private int VALID_INVITED_REWARDED_SALIVA = 20;

    @Autowired
    UserRepository userRepository;

    @Autowired
    UserInfoDao userInfoDao;

    @Autowired
    VipRepository vipRespository;

    @Autowired
    UserTagRepository userTagRepository;

    @Autowired
    TagRepository tagRepository;

    @Autowired
    InviteRepository inviteRepository;

    @Autowired
    VipService vipService;

    @Autowired
    TeacherStudentRepository teacherStudentRespository;

    @Autowired
    TeacherRepository teacherRepository;

    @Autowired
    VipRepository vipRepository;

    @Autowired
    HxAuthService hxAuthService;

    @Autowired
    HxUserApi hxUserApi;

    @Autowired
    CommentService commentService;

    @Override
    public UserSimpleInfoVo getUserById(String userId, String type) {
        if ("PARTYB".equals(type)) {
            UserEntity userEntity = userRepository.findOne(userId);
            UserSimpleInfoVo userSimpleInfoVo = new UserSimpleInfoVo();
            if(userEntity != null) {
                userSimpleInfoVo = convertUserSimpleInfo(userEntity);
                userSimpleInfoVo.setScore(commentService.getCommentScoreByReceive(userId));
            }
               return userSimpleInfoVo;
        } else if ("PARTYA".equals(type)) {
            TeacherEntity teacherEntity = teacherRepository.findOne(userId);
            UserSimpleInfoVo userSimpleInfoVo = new UserSimpleInfoVo();
            if(teacherEntity != null) {
                userSimpleInfoVo = converTeachserSimpleInfo(teacherEntity);
                userSimpleInfoVo.setScore(commentService.getCommentScoreByReceive(userId));
            }
            return userSimpleInfoVo;

        } else
            throw new CommonServiceException(ApiResponseCode.DATA_NOT_EXIST);
    }

    @Override
    public UserEntity getUserByMobile(String mobile) {
        List<UserEntity> userEntityList = userRepository.findByMobile(mobile);
        return ListUtils.getFirst(userEntityList);
    }

    @Override
    public UserEntity getUserByHxName(String hxName) {
        List<UserEntity> userEntityList = userRepository.findByHxName(hxName);
        return ListUtils.getFirst(userEntityList);
    }

    @Override
    public UserEntity getUserByUnionId(String unionId) {
        List<UserEntity> userEntities = userRepository.findByUnionId(unionId);

        if (userEntities != null && userEntities.size() > 0) {
            return userEntities.get(0);
        } else {
            return null;
        }
    }

    @Override
    public UserEntity getUserByOpenId(String openId) {
        List<UserEntity> userEntities = userRepository.findByOpenId(openId);

        if (userEntities != null && userEntities.size() > 0) {
            return userEntities.get(0);
        } else {
            return null;
        }
    }

    @Override
    public UserEntity getUserByAccount(String account) {
        List<UserEntity> userEntityList = userRepository.findByAccount(account);
        return ListUtils.getFirst(userEntityList);
    }

    @Override
    @Transactional
    public void createUser(UserEntity userEntity) {
        userRepository.save(userEntity);
    }

    @Override
    @Transactional
    public void modifyUser(UserInfoModifyVo userInfoModifyVo, UserInfo userInfo) {
        if ("PARTYB".equals(userInfo.getType())) {
            log.info("userInfoModifyVo =====", userInfoModifyVo.getNickname());
            log.info("userInfoModifyVo =====", userInfoModifyVo.getName());
            log.info("userInfoModifyVo =====", userInfoModifyVo.getInfo());
            UserEntity userEntity = userRepository.findOne(userInfo.getId());
            if (userEntity == null) {
                throw new CommonServiceException(ApiResponseCode.DATA_NOT_EXIST);
            }
            if(userInfoModifyVo.getName() != null) {
                userEntity.setName(userInfoModifyVo.getName());
            }
            if(userInfoModifyVo.getSex() != null) {
                userEntity.setSex(userInfoModifyVo.getSex());
            }
            if(userInfoModifyVo.getProvinceId() != null) {
                userEntity.setProvinceId(userInfoModifyVo.getProvinceId());
            }
            if(userInfoModifyVo.getCollege() != null) {
                userEntity.setCollege(userInfoModifyVo.getCollege());
            }
            if(userInfoModifyVo.getStudentCard() != null) {
                userEntity.setStudentCard(userInfoModifyVo.getStudentCard());
            }
            if(userInfoModifyVo.getInfo() != null) {
                userEntity.setInfo(userInfoModifyVo.getInfo());
            }
            if(userInfoModifyVo.getAvatar() != null) {
                userEntity.setAvatar(userInfoModifyVo.getAvatar());
            }
            if(userInfoModifyVo.getNickname() != null) {
                userEntity.setNickname(userInfoModifyVo.getNickname());
            }

//        if (!Strings.isNullOrEmpty(userEntity.getNickname())) {
//            HxUserInfoRequest hxUserRegisterRequest = HxUserInfoRequest.builder()
//                    .nickname(userEntity.getNickname())
//                    .build();
//            String accessToken = hxAuthService.getAndSetAccessToken();
//            Optional<HxUserInfoResponse> hxUserInfoResponseOptional = hxUserApi
//                    .updateNickname(userEntity.getMobile(), accessToken, hxUserRegisterRequest);
//            if (!hxUserInfoResponseOptional.isPresent()) {
//                throw new CommonServiceException(ApiResponseCode.HX_REQUEST_FAILED.getCode(), ApiResponseCode.HX_REQUEST_FAILED.getMsg());
//            }
//        }

            userRepository.save(userEntity);

            // if has login, update redis
            boolean perfect = Strings.isNullOrEmpty(userEntity.getName()) ? false : true;
            Optional<UserInfo> userInfoOptional = userInfoDao.getUserInfo(userEntity.getMobile());
            if (userInfoOptional.isPresent()) {
                userInfoDao.setUserInfoAttribute(userEntity.getMobile(), "perfect", String.valueOf(perfect));
            }
        } else {
            TeacherEntity teacherEntity = teacherRepository.findOne(userInfo.getId());
            if (teacherEntity == null) {
                throw new CommonServiceException(ApiResponseCode.DATA_NOT_EXIST);
            }
            if(userInfoModifyVo.getInfo() != null) {
                teacherEntity.setInfo(userInfoModifyVo.getInfo());
            }
            if(userInfoModifyVo.getAvatar() != null) {
                teacherEntity.setAvatar(userInfoModifyVo.getAvatar());
            }
            if(userInfoModifyVo.getNickname() != null) {
                teacherEntity.setNickname(userInfoModifyVo.getNickname());
            }
            teacherRepository.save(teacherEntity);
        }
    }

    @Override
    public MyPageVo getMyPage(String userId) {

        MyPageVo myPageVo = new MyPageVo();
        myPageVo.setUserInfo(convertUserSimpleInfo(userRepository.findOne(userId)));


        VipEntity vipEntity = vipService.getVipByUserId(userId);
        if (vipEntity != null) {
            myPageVo.setVipEntity(vipEntity);
        }

        List<UserTagEntity> userTagEntityList = userTagRepository.findByUserId(userId);


        List<TeacherStudentEntity> teacherStudentEntities = teacherStudentRespository.findByStudentId(userId);

        if (teacherStudentEntities.size() != 0){
            myPageVo.setIsHasTeacher(true);
            TeacherEntity teacherEntity = teacherRepository.findOne(teacherStudentEntities.get(0).getTeacherId());
            myPageVo.setTeacherEntity(teacherEntity);
        } else
            myPageVo.setIsHasTeacher(false);

        if (vipEntity != null){
            myPageVo.setIsVIP(vipEntity.getStatus() == ValidStatus.VALID);

        } else
            myPageVo.setIsVIP(false);

        return myPageVo;
    }

    @Override
    public UserInviteVo getUserInviteList(String userId) {
        int salivaRewarded = 0;
        UserInviteVo userInviteVo = new UserInviteVo();
        List<InviteEntity> inviteEntities = inviteRepository.findByInviterId(userId);
        List<String> validUserIds = Lists.newArrayList();
        List<String> invalidUserIds = Lists.newArrayList();
        for (InviteEntity inviteEntity : inviteEntities) {
            validUserIds.add(inviteEntity.getInviteeId());
        }
        List<UserEntity> validUsers = userRepository.findByIdIn(validUserIds);
        userInviteVo.setValidList(convertUserSimpleInfo(validUsers));
        return userInviteVo;
    }

    /**
     * 甲方 乙方邀请公用一个表
     * @param inviterId
     * @param inviteeId
     */
    @Override
    @Transactional
    public void addUserInvite(String inviterId, String inviteeId) {
        InviteEntity inviteEntity = new InviteEntity();
        inviteEntity.setId(UUIDUtils.getUUID());
        inviteEntity.setInviterId(inviterId);
        inviteEntity.setInviteeId(inviteeId);
        inviteEntity.setCreateTime(new Date());

        inviteRepository.save(inviteEntity);
    }

    @Override
    public UserEntity getUserByInviteCode(String inviteCode) {
        List<UserEntity> userEntities = userRepository.findByInviteCode(inviteCode);
        return ListUtils.getFirst(userEntities);
    }

    private List<UserSimpleInfoVo> convertUserSimpleInfo(List<UserEntity> userEntities) {
        List<UserSimpleInfoVo> userSimpleInfoVoList = Lists.newArrayList();
        for (UserEntity userEntity : userEntities) {
            UserSimpleInfoVo userSimpleInfoVo = new UserSimpleInfoVo();
            BeanUtils.copyProperties(userEntity, userSimpleInfoVo);
            userSimpleInfoVoList.add(userSimpleInfoVo);
        }
        return userSimpleInfoVoList;
    }

    private UserSimpleInfoVo convertUserSimpleInfo(UserEntity userEntity) {
        UserSimpleInfoVo userSimpleInfoVo = new UserSimpleInfoVo();
        BeanUtils.copyProperties(userEntity, userSimpleInfoVo);
        userSimpleInfoVo.setHxPwd(userEntity.getPassword());
        userSimpleInfoVo.setHxName(userEntity.getHxName());
        return userSimpleInfoVo;
    }

    private UserSimpleInfoVo converTeachserSimpleInfo(TeacherEntity teacherEntity) {
        UserSimpleInfoVo userSimpleInfoVo = new UserSimpleInfoVo();
        BeanUtils.copyProperties(teacherEntity, userSimpleInfoVo);
        userSimpleInfoVo.setHxName(teacherEntity.getHxName());
        userSimpleInfoVo.setHxPwd(teacherEntity.getPassword());
        return userSimpleInfoVo;
    }

    @Override
    public List<String> getUserTag(String userId) {
        List<String> tagList = Lists.newArrayList();
        List<UserTagEntity> userTagEntities = userTagRepository.findByUserId(userId);
        for (UserTagEntity userTagEntity : userTagEntities) {
            tagList.add(userTagEntity.getTagName());
        }
        return tagList;
    }

    @Override
    public UserListVo getUserList(Pageable pageable) {
        UserListVo userListVo = new UserListVo();

        Page<UserEntity> userEntities;

        List<UserInfoVo> userInfoVoList = new ArrayList<>();


        userEntities =  userRepository.findAllByOrderByCreateTimeDesc(pageable);

        for (UserEntity userEntity : userEntities) {
            UserInfoVo userInfoVo = new UserInfoVo();
            userInfoVo.setPassword(userEntity.getPassword());
            userInfoVo.setStatus(userEntity.getStatus());
            userInfoVo.setMobile(userEntity.getMobile());
            userInfoVo.setNickname(userEntity.getNickname());
            userInfoVo.setAccount(userEntity.getAccount());
            userInfoVo.setAvatar(userEntity.getAvatar());
            userInfoVo.setCollege(userEntity.getCollege());
            userInfoVo.setCreateTime(userEntity.getCreateTime());
            userInfoVo.setHxId(userEntity.getHxId());
            userInfoVo.setId(userEntity.getId());
            userInfoVo.setInviteCode(userEntity.getInviteCode());
            userInfoVo.setMobile(userEntity.getMobile());
            userInfoVo.setName(userEntity.getName());
            userInfoVo.setUpdateTime(userEntity.getUpdateTime());
            userInfoVo.setSex(userEntity.getSex());
            userInfoVo.setProvinceId(userEntity.getProvinceId());

            userInfoVoList.add(userInfoVo);

        }

        userListVo.setTotalCount(userEntities.getTotalElements());
        userListVo.setList(userInfoVoList);


        return userListVo;
    }

    @Override
    public UserListVo getUserListByName(String name, Pageable pageable) {
        UserListVo userListVo = new UserListVo();

        Page<UserEntity> userEntities;

        List<UserInfoVo> userInfoVoList = new ArrayList<>();


        userEntities =  userRepository.findByNicknameContainingOrderByCreateTimeDesc(name,pageable);

        for (UserEntity userEntity : userEntities) {
            UserInfoVo userInfoVo = new UserInfoVo();
            userInfoVo.setPassword(userEntity.getPassword());
            userInfoVo.setStatus(userEntity.getStatus());
            userInfoVo.setMobile(userEntity.getMobile());
            userInfoVo.setNickname(userEntity.getNickname());
            userInfoVo.setAccount(userEntity.getAccount());
            userInfoVo.setAvatar(userEntity.getAvatar());
            userInfoVo.setCollege(userEntity.getCollege());
            userInfoVo.setCreateTime(userEntity.getCreateTime());
            userInfoVo.setHxId(userEntity.getHxId());
            userInfoVo.setId(userEntity.getId());
            userInfoVo.setInviteCode(userEntity.getInviteCode());
            userInfoVo.setMobile(userEntity.getMobile());
            userInfoVo.setName(userEntity.getName());
            userInfoVo.setUpdateTime(userEntity.getUpdateTime());
            userInfoVo.setSex(userEntity.getSex());
            userInfoVo.setProvinceId(userEntity.getProvinceId());
            List<UserTagEntity> userTagEntity = userTagRepository.findByUserId(userEntity.getId());

            List<VipEntity> vipEntity = vipRepository.findByUserId(userInfoVo.getId());

            userInfoVoList.add(userInfoVo);

        }

        userListVo.setTotalCount(userEntities.getTotalElements());
        userListVo.setList(userInfoVoList);


        return userListVo;
    }

    @Override
    @Transactional
    public void delTag(DelBody name) {
        userTagRepository.deleteByTagName(name.getId());
    }

    @Transactional
    @Override
    public void addTag(String name, String userId) {
        UserTagEntity userTagEntity = new UserTagEntity();
        userTagEntity.setUserId(userId);
        userTagEntity.setId(UUIDUtils.getUUID());
        userTagEntity.setTagName(name);
        userTagRepository.save(userTagEntity);
    }


    @Override
    @Transactional
    public void modTagList(List<String> tagNameList, String userId) {
        userTagRepository.deleteByUserId(userId);
        for (String name : tagNameList) {
            UserTagEntity userTagEntity = new UserTagEntity();
            userTagEntity.setUserId(userId);
            userTagEntity.setId(UUIDUtils.getUUID());
            userTagEntity.setTagName(name);
            userTagRepository.save(userTagEntity);
        }
    }

    @Override
    public TeacherStudentEntity getTeacherStudent(String studentId) {
        List<TeacherStudentEntity> teacherStudentEntity = teacherStudentRespository.findByStudentId(studentId);
        return ListUtils.getFirst(teacherStudentEntity);
    }

    @Override
    public UserListVo getUserListMulti(String id, String mobile, String nickname, String status, Pageable pageable) {
        Page <UserEntity> userEntities;
        List<UserInfoVo> userInfoVoList = new ArrayList<>();
        UserListVo userListVo = new UserListVo();

        if(id == null && mobile == null && nickname == null && status == null) {
            userEntities = userRepository.findAll(pageable );
        } else {
            userEntities = userRepository.findMultList(id, mobile, nickname, status, pageable );
        }

        for (UserEntity userEntity : userEntities) {
            UserInfoVo userInfoVo = new UserInfoVo();
            userInfoVo.setPassword(userEntity.getPassword());
            userInfoVo.setStatus(userEntity.getStatus());
            userInfoVo.setMobile(userEntity.getMobile());
            userInfoVo.setNickname(userEntity.getNickname());
            userInfoVo.setAccount(userEntity.getAccount());
            userInfoVo.setAvatar(userEntity.getAvatar());
            userInfoVo.setCollege(userEntity.getCollege());
            userInfoVo.setCreateTime(userEntity.getCreateTime());
            userInfoVo.setHxId(userEntity.getHxId());
            userInfoVo.setId(userEntity.getId());
            userInfoVo.setInviteCode(userEntity.getInviteCode());
            userInfoVo.setMobile(userEntity.getMobile());
            userInfoVo.setName(userEntity.getName());
            userInfoVo.setUpdateTime(userEntity.getUpdateTime());
            userInfoVo.setSex(userEntity.getSex());
            userInfoVo.setProvinceId(userEntity.getProvinceId());

            userInfoVoList.add(userInfoVo);

        }
        userListVo.setTotalCount(userEntities.getTotalElements());
        userListVo.setList(userInfoVoList);

        return userListVo;
    }

    @Override
    public void del(DelBody id) {
        userRepository.delete(id.getId());
    }

    @Override
    public void delList(DelListBody idList) {
        for(String id : idList.getList()) {
            userRepository.delete(id);
        }
    }

    @Override
    public void modify(UserInfoManageModifyVo userInfoModifyVo) {
        UserEntity userEntity = userRepository.findOne(userInfoModifyVo.getId());
        if (userEntity == null) {
            throw new CommonServiceException(ApiResponseCode.DATA_NOT_EXIST);
        }

        userEntity.setInfo(userInfoModifyVo.getInfo());
        userEntity.setName(userInfoModifyVo.getName());
        userEntity.setSex(userInfoModifyVo.getSex());
        userEntity.setProvinceId(userInfoModifyVo.getProvinceId());
        userEntity.setCollege(userInfoModifyVo.getCollege());
        userEntity.setStatus(userInfoModifyVo.getStatus());

        // 认证送邀请人积分
        if ("0".equals(userEntity.getAuth()) && "1".equals(userInfoModifyVo.getAuth())) {
            InviteEntity inviter = inviteRepository.findByInviteeId(userEntity.getId());
            UserEntity inviterEntity = userRepository.findOne(inviter.getInviterId());
            inviterEntity.setPoint(inviterEntity.getPoint() + 2);
            inviterEntity.setUpdateTime(new Date());
            userRepository.save(inviterEntity);
        }
        userEntity.setAuth(userInfoModifyVo.getAuth());
        userRepository.save(userEntity);

    }

}
